// Copyright (C) joyinter
// All rights reserved.
// 
// Author : Jiang Li
// Date   : 2004-6-18

#ifndef __REFPTR_H_COMMON_BASE__
#define __REFPTR_H_COMMON_BASE__

#pragma once

#include "thread.h"

//##ModelId=44CF1757034B
template<typename T>
class CJoyRefPtr
{
protected:
	//##ModelId=44CF17570399
    struct CRefData
    {
		//##ModelId=44CF1757039C
        T*  ptr;
		//##ModelId=44CF175703AA
        CJoyAtomCount   ref;

		//##ModelId=44CF175703AE
        CRefData(T* p = NULL):
            ptr(p),
            ref(1)
        {
        }
    };
	//##ModelId=44CF1757034E
    CRefData* m_pData;

	//##ModelId=44CF1757035F
    static CRefData m_defaultData;

	//##ModelId=44CF17570363
    void FreePtr()
    {
        if(m_pData->ptr != NULL)
        {
            delete m_pData->ptr;
        }
    }
	//##ModelId=44CF17570364
    void Free()
    {
        if(--m_pData->ref == 0)
        {
            FreePtr();
            delete m_pData;
        }
    }

	//##ModelId=44CF17570365
    void Attach(CRefData* pData)
    {
        pData->ref ++;
        m_pData = pData;
    }
public:
	//##ModelId=44CF1757036C
    CJoyRefPtr()
    {
        Attach(&m_defaultData);
    }
	//##ModelId=44CF1757036D
    CJoyRefPtr(T* ptr)
    {
        m_pData = new CRefData(ptr);
    }
	//##ModelId=44CF1757036F
    CJoyRefPtr(const CJoyRefPtr& rptr)
    {
        Attach(rptr.m_pData);
    }
	//##ModelId=44CF17570371
    ~CJoyRefPtr()
    {
        Free();
    }

	//##ModelId=44CF17570372
    T* operator -> () const
    {
        return m_pData->ptr;
    }

	//##ModelId=44CF1757037A
    CJoyRefPtr& operator = (const CJoyRefPtr& rptr)
    {
        if(m_pData != rptr.m_pData)
        {
            Free();
            Attach(rptr.m_pData);
        }
        return *this;
    }

	//##ModelId=44CF1757037C
    CJoyRefPtr& operator = (T* ptr)
    {
        if(--m_pData->ref == 0)
        {
            FreePtr();
            m_pData->ref ++;
            m_pData->ptr = ptr;
        }
        else
        {
            m_pData = new CRefData(ptr);
        }
        return *this;
    }

	//##ModelId=44CF1757037E
    bool operator == (const CJoyRefPtr& rptr) const
    {
        return m_pData->ptr == rptr.m_pData->ptr;
    }
	//##ModelId=44CF17570381
    bool operator == (T* ptr) const
    {
        return m_pData->ptr == ptr;
    }
	//##ModelId=44CF1757038A
    bool operator != (const CJoyRefPtr& rptr) const
    {
        return m_pData->ptr != rptr.m_pData->ptr;
    }
	//##ModelId=44CF1757038D
    bool operator != (T* ptr) const
    {
        return m_pData->ptr != ptr;
    }
	//##ModelId=44CF17570390
    operator T* () const
    {
        return m_pData->ptr;
    }
	//##ModelId=44CF17570392
    void* GetAddress() const
    {
        return (void*)this;
    }

	//##ModelId=44CF17570394
    bool Valid() const
    {
        return m_pData->ptr != NULL;
    }

	//##ModelId=44CF17570396
    T* Detach()
    {
        T* ptr = m_pData->ptr;
        m_pData->ptr = NULL;
        return ptr;
    }

};

template<typename T>
typename CJoyRefPtr<T>::CRefData CJoyRefPtr<T>::m_defaultData;



#endif  // __REFPTR_H_COMMON_BASE__
